package com.iot.gateway.tsl.service.impl;

import com.iot.gateway.tsl.mapper.TslDeviceSpecMapper;
import com.iot.gateway.tsl.model.OpenTokenRequest;
import com.iot.gateway.tsl.model.OpenTokenResponse;
import com.iot.gateway.tsl.model.TslDeviceSpecEntity;
import com.iot.gateway.tsl.qo.SpecQo;
import com.iot.gateway.tsl.service.TslDeviceSpecService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.server.ResponseStatusException;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 设备协议扩展管理 Service 实现
 */
@Service
public class TslDeviceSpecServiceImpl implements TslDeviceSpecService {

    private final TslDeviceSpecMapper mapper;
    private final RestTemplate restTemplate;
    private final String       openTokenUrl;

    public TslDeviceSpecServiceImpl(
        final TslDeviceSpecMapper mapper,
        RestTemplate restTemplate,
        @Value("${open.token.url}") String openTokenUrl) {
        this.restTemplate= restTemplate;
        this.openTokenUrl= openTokenUrl;
        this.mapper = mapper;
    }

    /**
     * 全量写入或覆盖指定设备的 specs。
     * 如果 specs 中包含 tokenConfig，则自动调用 OpenToken 接口，
     * 并将返回的 token 写入到 specs.headers.Authorization 中。
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setSpecs(final String deviceId, final Map<String, Object> specs) {
        // 1. 处理 tokenConfig
        System.out.println(specs);
        if (specs.containsKey("tokenConfig")) {
            @SuppressWarnings("unchecked")
            Map<String, String> tokenConfig = (Map<String, String>) specs.get("tokenConfig");
            // 构建 OpenTokenRequest
            OpenTokenRequest.Params params = new OpenTokenRequest.Params();
            params.setAppId(tokenConfig.get("appId"));
            params.setAppSecretKey(tokenConfig.get("appSecretKey"));
            OpenTokenRequest req = new OpenTokenRequest();
            req.setParams(params);

            // 调用 OpenTokenService 获取 open_token
            String token;
            try {
                token = getOpenToken(null, req);
            } catch (Exception ex) {
                throw new ResponseStatusException(HttpStatus.BAD_GATEWAY, "调用 OpenToken 接口失败", ex
                );
            }

            // 将 token 写入 headers.Authorization
            @SuppressWarnings("unchecked")
            Map<String, Object> headers = (Map<String, Object>) specs.get("headers");
            if (headers == null) {
                headers = new LinkedHashMap<>();
                specs.put("headers", headers);
            }
            headers.put("Authorization", token);

            // 移除 tokenConfig 避免冗余
            specs.remove("tokenConfig");
        }

        // 2. 持久化 specs：更新或插入
        TslDeviceSpecEntity entity = new TslDeviceSpecEntity();
        entity.setDeviceId(deviceId);
        entity.setSpecs(specs);
        if (mapper.updateById(entity) == 0) {
            mapper.insert(entity);
        }
    }

    /**
     * 更新指定设备的单个 spec 字段
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSpec(final String deviceId, final String specKey, final SpecQo specQo) {
        TslDeviceSpecEntity existing = mapper.selectById(deviceId);
        Map<String, Object> allSpecs = existing != null
                ? new LinkedHashMap<>(existing.getSpecs())
                : new LinkedHashMap<>();
        allSpecs.put(specKey, specQo.getValue());
        setSpecs(deviceId, allSpecs);
    }

    /**
     * 删除指定设备的单个 spec 字段
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteSpec(final String deviceId, final String specKey) {
        TslDeviceSpecEntity existing = mapper.selectById(deviceId);
        if (existing != null) {
            Map<String, Object> allSpecs = new LinkedHashMap<>(existing.getSpecs());
            allSpecs.remove(specKey);
            setSpecs(deviceId, allSpecs);
        }
    }

    /**
     * 读取指定设备的所有 specs
     */
    @Override
    public Map<String, Object> getSpecs(final String deviceId) {
        TslDeviceSpecEntity existing = mapper.selectById(deviceId);
        return existing != null
                ? existing.getSpecs()
                : Map.of();
    }

    @Override
    public String getOpenToken(String userId, OpenTokenRequest request) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        if (userId != null && !userId.isEmpty()) {
            headers.add("UserId", userId);
        }

        HttpEntity<OpenTokenRequest> entity = new HttpEntity<>(request, headers);
        ResponseEntity<OpenTokenResponse> resp = restTemplate.postForEntity(openTokenUrl, entity, OpenTokenResponse.class);

        if (resp.getStatusCode() != HttpStatus.OK || resp.getBody() == null) {
            throw new ResponseStatusException(HttpStatus.BAD_GATEWAY, "调用 OpenToken 服务失败");
        }

        OpenTokenResponse body = resp.getBody();
        if (!"00".equals(body.getTxCode())) {
            String err = (body.getErrorInfo() != null ? body.getErrorInfo().getMessage() : "未知错误");
            throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "获取 open_token 失败: " + err);
        }

        return body.getData().getOpenToken();
    }
}
